﻿namespace ImageProcessing
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Domains;
    using MathWorks.MATLAB.NET.Arrays;
    using MathWorks.MATLAB.NET.Utility;
    using MATLABApp;
    using Test2;
    using Untitled1;

    /// <summary>
    /// Operations for the fourier functionalities
    /// </summary>
    public class FourierOperations
    {
        /// <summary>
        /// Gets the magnitude.
        /// </summary>
        /// <param name="redMagnitude">The red magnitude.</param>
        /// <param name="greenMagnitude">The green magnitude.</param>
        /// <param name="blueMagnitude">The blue magnitude.</param>
        /// <param name="realRed">The real red.</param>
        /// <param name="realGreen">The real green.</param>
        /// <param name="realBlue">The real blue.</param>
        /// <param name="imagRed">The imag red.</param>
        /// <param name="imagGreen">The imag green.</param>
        /// <param name="imagBlue">The imag blue.</param>
        public static void GetMagnitude(ref double[,] redMagnitude, ref double[,] greenMagnitude, ref double[,] blueMagnitude, double[,] realRed, double[,] realGreen, double[,] realBlue, double[,] imagRed, double[,] imagGreen, double[,] imagBlue)
        {
            int u = realRed.GetLength(0);
            int v = realRed.GetLength(1);

            redMagnitude = new double[u, v];
            greenMagnitude = new double[u, v];
            blueMagnitude = new double[u, v];
            for (int i = 0; i < u; i++)
            {
                for (int j = 0; j < v; j++)
                {
                    redMagnitude[i, j] = Math.Sqrt(Math.Pow(realRed[i, j], 2) + Math.Pow(imagRed[i, j], 2));
                    greenMagnitude[i, j] = Math.Sqrt(Math.Pow(realGreen[i, j], 2) + Math.Pow(imagGreen[i, j], 2));
                    blueMagnitude[i, j] = Math.Sqrt(Math.Pow(realBlue[i, j], 2) + Math.Pow(imagBlue[i, j], 2));
                }
            }
        }

        /// <summary>
        /// Gets the log magnitude.
        /// </summary>
        /// <param name="redLogMagnitude">The red log magnitude.</param>
        /// <param name="greenLogMagnitude">The green log magnitude.</param>
        /// <param name="blueLogMagnitude">The blue log magnitude.</param>
        /// <param name="grayLogMagnitude">The gray log magnitude.</param>
        /// <param name="redMagnitude">The red magnitude.</param>
        /// <param name="greenMagnitude">The green magnitude.</param>
        /// <param name="blueMagnitude">The blue magnitude.</param>
        public static void GetLogMagnitude(ref double[,] redLogMagnitude, ref double[,] greenLogMagnitude, ref double[,] blueLogMagnitude, ref double[,] grayLogMagnitude, double[,] redMagnitude, double[,] greenMagnitude, double[,] blueMagnitude)
        {
            int u = redMagnitude.GetLength(0);
            int v = redMagnitude.GetLength(1);

            redLogMagnitude = new double[u, v];
            greenLogMagnitude = new double[u, v];
            blueLogMagnitude = new double[u, v];
            grayLogMagnitude = new double[u, v];
            for (int i = 0; i < u; i++)
            {
                for (int j = 0; j < v; j++)
                {
                    redLogMagnitude[i, j] = Math.Log(redMagnitude[i, j] + 0.1);
                    greenLogMagnitude[i, j] = Math.Log(greenMagnitude[i, j] + 0.1);
                    blueLogMagnitude[i, j] = Math.Log(blueMagnitude[i, j] + 0.1);
                    grayLogMagnitude[i, j] = (redLogMagnitude[i, j] + greenLogMagnitude[i, j] + blueLogMagnitude[i, j]) / 3;
                }
            }
        }

        /// <summary>
        /// Gets the fourier from matlab.
        /// </summary>
        /// <param name="realRed">The real red.</param>
        /// <param name="realGreen">The real green.</param>
        /// <param name="realBlue">The real blue.</param>
        /// <param name="imagRed">The imag red.</param>
        /// <param name="imagGreen">The imag green.</param>
        /// <param name="imagBlue">The imag blue.</param>
        /// <param name="matlabClassObj">The matlab class obj.</param>
        /// <param name="redImage">The red image.</param>
        /// <param name="greenImage">The green image.</param>
        /// <param name="blueImage">The blue image.</param>
        public static void GetFourierFromMatlab(ref double[,] realRed, ref double[,] realGreen, ref double[,] realBlue, ref double[,] imagRed, ref double[,] imagGreen, ref double[,] imagBlue, Class1 matlabClassObj, double[,] redImage, double[,] greenImage, double[,] blueImage)
        {
            MWNumericArray temp;

            // MWNumericArray RedArg1 = (MWNumericArray)matlabClassObj.ERealFourier((MWNumericArray)redImage);
            // realRed = (double[,])RedArg1.ToArray();

            // NeighborOpers MATLAB = new NeighborOpers();hh 
            // MWNumericArray NewR = (MWNumericArray)MATLAB.LocalVariance((MWNumericArray)redImage, 3);
            // double[,] R = (double[,])NewR.ToArray();
            MWArray[] redArg = matlabClassObj.EFourier(2, (MWNumericArray)redImage);
            temp = (MWNumericArray)redArg[0];
            realRed = (double[,])temp.ToArray(MWArrayComponent.Real);
            temp = (MWNumericArray)redArg[1];
            imagRed = (double[,])temp.ToArray(MWArrayComponent.Real);

            MWArray[] greenArg = matlabClassObj.EFourier(2, (MWNumericArray)greenImage);
            temp = (MWNumericArray)greenArg[0];
            realGreen = (double[,])temp.ToArray(MWArrayComponent.Real);
            temp = (MWNumericArray)greenArg[1];
            imagGreen = (double[,])temp.ToArray(MWArrayComponent.Real);

            MWArray[] blueArg = matlabClassObj.EFourier(2, (MWNumericArray)blueImage);
            temp = (MWNumericArray)blueArg[0];
            realBlue = (double[,])temp.ToArray(MWArrayComponent.Real);
            temp = (MWNumericArray)blueArg[1];
            imagBlue = (double[,])temp.ToArray(MWArrayComponent.Real);
        }

        /// <summary>
        /// Gets the spatial from matlab.
        /// </summary>
        /// <param name="redSpatial">The red spatial.</param>
        /// <param name="greenSpatial">The green spatial.</param>
        /// <param name="blueSpatial">The blue spatial.</param>
        /// <param name="matlabClassObj">The matlab class obj.</param>
        /// <param name="realRed">The real red.</param>
        /// <param name="realGreen">The real green.</param>
        /// <param name="realBlue">The real blue.</param>
        /// <param name="imagRed">The imag red.</param>
        /// <param name="imagGreen">The imag green.</param>
        /// <param name="imagBlue">The imag blue.</param>
        public static void GetSpatialFromMatlab(ref double[,] redSpatial, ref double[,] greenSpatial, ref double[,] blueSpatial, Class1 matlabClassObj, double[,] realRed, double[,] realGreen, double[,] realBlue, double[,] imagRed, double[,] imagGreen, double[,] imagBlue)
        {
            MWNumericArray redArg = (MWNumericArray)matlabClassObj.ESpatial((MWNumericArray)realRed, (MWNumericArray)imagRed);
            redSpatial = (double[,])redArg.ToArray(MWArrayComponent.Real);

            MWNumericArray greenArg = (MWNumericArray)matlabClassObj.ESpatial((MWNumericArray)realGreen, (MWNumericArray)imagGreen);
            greenSpatial = (double[,])greenArg.ToArray(MWArrayComponent.Real);

            MWNumericArray blueArg = (MWNumericArray)matlabClassObj.ESpatial((MWNumericArray)realBlue, (MWNumericArray)imagBlue);
            blueSpatial = (double[,])blueArg.ToArray(MWArrayComponent.Real);
        }

        /// <summary>
        /// Separates the colors.
        /// </summary>
        /// <param name="redImage">The red image.</param>
        /// <param name="greenImage">The green image.</param>
        /// <param name="blueImage">The blue image.</param>
        /// <param name="image">The image.</param>
        public static void SeparateColors(ref double[,] redImage, ref double[,] greenImage, ref double[,] blueImage, DImage image)
        {
            int u = image.Height;
            int v = image.Width;

            redImage = new double[u, v];
            greenImage = new double[u, v];
            blueImage = new double[u, v];
            for (int i = 0; i < u; i++)
            {
                for (int j = 0; j < v; j++)
                {
                    redImage[i, j] = image.ImageStructArray[i, j].R;
                    greenImage[i, j] = image.ImageStructArray[i, j].G;
                    blueImage[i, j] = image.ImageStructArray[i, j].B;
                }
            }
        }
     
        /// <summary>
        /// Separates the colors.
        /// </summary>
        /// <param name="redImage">The red image.</param>
        /// <param name="greenImage">The green image.</param>
        /// <param name="blueImage">The blue image.</param>
        /// <param name="image">The image.</param>
        public static void SeparateColors(ref double[,] redImage, ref double[,] greenImage, ref double[,] blueImage, ImageStructure[,] image)
        {
            int u = image.GetLength(0);
            int v = image.GetLength(1);

            redImage = new double[u, v];
            greenImage = new double[u, v];
            blueImage = new double[u, v];
            for (int i = 0; i < u; i++)
            {
                for (int j = 0; j < v; j++)
                {
                    redImage[i, j] = image[i, j].R;
                    greenImage[i, j] = image[i, j].G;
                    blueImage[i, j] = image[i, j].B;
                }
            }
        }

        /// <summary>
        /// Recollects the image.
        /// </summary>
        /// <param name="redSpatial">The red spatial.</param>
        /// <param name="greenSpatial">The green spatial.</param>
        /// <param name="blueSpatial">The blue spatial.</param>
        /// <param name="postProcessing">The post processing.</param>
        /// <returns>Recollected image</returns>
        public static ImageStructure[,] RecollectImage(double[,] redSpatial, double[,] greenSpatial, double[,] blueSpatial, PostProcessing postProcessing)
        {
            int u = redSpatial.GetLength(0);
            int v = redSpatial.GetLength(1);
            ImageStructure[,] newImage = new ImageStructure[u, v];

            if (PostProcessing.None == postProcessing)
            {
                for (int i = 0; i < u; i++)
                {
                    for (int j = 0; j < v; j++)
                    {
                        newImage[i, j].R = (byte)redSpatial[i, j];
                        newImage[i, j].G = (byte)greenSpatial[i, j];
                        newImage[i, j].B = (byte)blueSpatial[i, j];
                    }
                }
            }
            else if (PostProcessing.Normalization == postProcessing)
            {
                return PixelOperation.Normalization(newImage, u, v, redSpatial, greenSpatial, blueSpatial);
            }
            else if (PostProcessing.CuttOff == postProcessing)
            {
                return PixelOperation.CutOffImage(redSpatial, greenSpatial, blueSpatial);
            }
            else
            {
                return null;
            }

            return newImage;
        }
    }
}
